package org.example.io;

import org.example.util.FileUtil;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;

public class bio与nio的对比 {



    /**
     * bio 不使用 BufferedReader BufferedWriter
     * @param input
     * @param out
     * @throws Exception
     */
    public static void bioNoBuffered(String input, String out,int size) throws Exception {
        long start = System.currentTimeMillis();

        FileInputStream fileInputStream = new FileInputStream(input);
        FileOutputStream fileOutputStream = new FileOutputStream(out);

        byte[] bytes = new byte[size];
        int len;

        while ((len = fileInputStream.read(bytes)) != -1) {
            fileOutputStream.write(bytes, 0, len);
        }

        fileInputStream.close();
        fileOutputStream.close();

        long end = System.currentTimeMillis();

        double time = (end - start) * 1.0 / 1000;

        System.out.println("bioNoBuffered执行时间为" + time + "秒");

    }

    /**
     * bio 使用 BufferedInputStream BufferedOutputStream
     * @param input
     * @param out
     * @throws Exception
     */
    public static void bioYesBuffered(String input, String out,int size) throws Exception {
        long start = System.currentTimeMillis();

        FileInputStream fileInputStream = new FileInputStream(input);
        FileOutputStream fileOutputStream = new FileOutputStream(out);


        BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream,size);
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream,size);

        byte[] bytes = new byte[size];
        int len;

        while ((len = bufferedInputStream.read(bytes)) != -1) {
            bufferedOutputStream.write(bytes, 0, len);
        }

        bufferedInputStream.close();
        bufferedOutputStream.close();
        long end = System.currentTimeMillis();

        double time = (end - start) * 1.0 / 1000;

        System.out.println("bioYesBuffered执行时间为" + time + "秒");

    }

    /**
     * nio 不使用 allocateDirect
     * @param input
     * @param out
     * @throws Exception
     */
    public static void nioNoAllocateDirect(String input, String out,int size) throws Exception {
        long start = System.currentTimeMillis();

        Path inputPath = Paths.get(input);
        Path outPath = Paths.get(out);
        FileChannel inputFileChannel = FileChannel.open(inputPath, StandardOpenOption.READ);
        FileChannel outFileChannel = FileChannel.open(outPath, StandardOpenOption.WRITE,StandardOpenOption.CREATE);

        ByteBuffer byteBuffer = ByteBuffer.allocate(size);

        System.out.println("是否是直接缓冲区:" + byteBuffer.isDirect());

        while (inputFileChannel.read(byteBuffer) != -1){
            // 切换到写模式
            byteBuffer.flip();
            outFileChannel.write(byteBuffer);
            // 清空缓冲区，准备下一次读取
            byteBuffer.clear();
        }

        inputFileChannel.close();
        outFileChannel.close();

        long end = System.currentTimeMillis();

        double time = (end - start) * 1.0 / 1000;

        System.out.println("nioNoAllocateDirect执行时间为" + time + "秒");

    }

    /**
     * nio 使用 allocateDirect
     * @param input
     * @param out
     * @throws Exception
     */
    public static void nioYesAllocateDirect(String input, String out,int size) throws Exception {
        long start = System.currentTimeMillis();

        Path inputPath = Paths.get(input);
        Path outPath = Paths.get(out);

        FileChannel inputFileChannel = FileChannel.open(inputPath, StandardOpenOption.READ);
        FileChannel outFileChannel = FileChannel.open(outPath, StandardOpenOption.WRITE,StandardOpenOption.CREATE);

        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(size);

        System.out.println("是否是直接缓冲区:" + byteBuffer.isDirect());

        while (inputFileChannel.read(byteBuffer) != -1){
            // 切换到写模式
            byteBuffer.flip();
            outFileChannel.write(byteBuffer);
            // 清空缓冲区，准备下一次读取
            byteBuffer.clear();
        }

        inputFileChannel.close();
        outFileChannel.close();

        long end = System.currentTimeMillis();

        double time = (end - start) * 1.0 / 1000;

        System.out.println("nioYesAllocateDirect执行时间为" + time + "秒");
    }

    /**
     * nio 零拷贝技术
     * @param input
     * @param out
     * @throws IOException
     */
    public static void nioTransferTo(String input, String out) throws IOException {
        long start = System.currentTimeMillis();

        Path inputPath = Paths.get(input);
        Path outPath = Paths.get(out);

        FileChannel inputFileChannel = FileChannel.open(inputPath, StandardOpenOption.READ);
        FileChannel outFileChannel = FileChannel.open(outPath, StandardOpenOption.WRITE,StandardOpenOption.CREATE);

        inputFileChannel.transferTo(0,inputFileChannel.size(),outFileChannel);

        inputFileChannel.close();
        outFileChannel.close();

        long end = System.currentTimeMillis();

        double time = (end - start) * 1.0 / 1000;

        System.out.println("nioTransferTo执行时间为" + time + "秒");
    }


    public static void main(String[] args) throws Exception {
//        FileUtil.createFile("D:\\java-project\\java-test\\copy\\a.txt",1024);

        String input = "D:\\java-project\\java-test\\copy\\a.txt";
        String out = "D:\\java-project\\java-test\\copy\\";
        int count = 10;
//        for(int i = 1;i<=count;i++){
//            bioNoBuffered(input,out+ UUID.randomUUID().toString()+".txt",1024 * 1024 * 16);
//            bioYesBuffered(input,out+ UUID.randomUUID().toString()+".txt",1024 * 1024 * 16);
//            nioNoAllocateDirect(input,out+ UUID.randomUUID().toString()+".txt",1024 * 1024 * 16);
//            nioYesAllocateDirect(input,out+ UUID.randomUUID().toString()+".txt",1024 * 1024 * 16);
//            nioTransferTo(input,out+ UUID.randomUUID().toString()+".txt");
//        }
//        bioNoBuffered(input,out+ UUID.randomUUID().toString()+".txt",1024 * 1024 * 16);
//        bioYesBuffered(input,out+ UUID.randomUUID().toString()+".txt",1024 * 1024 * 16);
//        nioNoAllocateDirect(input,out+ UUID.randomUUID().toString()+".txt",1024 * 1024 * 16);
//        nioYesAllocateDirect(input,out+ UUID.randomUUID().toString()+".txt",1024 * 1024 * 16);

    }
}
